<?php
/**
 * @name Auth: Authorisation and Permission managment library extension
 * @version 0.4.10, December 15, 2007
 * @copyright &copy; 2006 Novachok, A.
 * @author iSnow (Novachok Alexandr) <novachok@ukr.net>
 * @package Authorisation and Prmission managment Library
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

class auth
{
   var $timeout      = 0;     # Auth session live timeout
   var $logedstatus  = false; # Signal about loged or not users status
   var $loginIsEmail = false; # is email Users login?
   var $DB           = null;  # Reference to DateBase library class
   var $root         = false; # Root login - Hi level access acount
   var $rootpwd      = false; # Root password
   var $permission   = false; # Permissions for user
   var $session      = null;
   var $crypt        = false;
   var $user         = array();
   var $cookie       = array();
   var $authsource   = array('table'=>false, 'login'=>false, 'pwd'=>false, 'permissions'=>false, 'lastloged'=>false, 'email'=>false, 'valid'=>false);
   // Levels for ERROR: USER - clients errors; SYSTEM - system errors;
   var $error        = false;
   var $serial       = 20071215;
   var $version      = "0.4.10";


   /**
     * Constructor of Authorization class
     *
     * @param string $session - session name, default: auth
     * @param integer $timeout - authorization session live, defalt: 0 - so unlimited
     * @param object $DB - Object identifier
     * @param array $table_params - authorization table params
     * @return auth
     */
   function auth($session = 'auth', $timeout = 0, $DB = false, $table_params = array())
   {
      /*
      *  CONSTRUCT->table_params is DB info for authorization - is array with fields:
      *  [0] or ['table']       = table name;
      *  [1] or ['login']       = login field;
      *  [2] or ['pwd']         = password field;
      *  [3] or ['permissions'] = perissions field;
      *  [4] or ['lastloged']   = last loged time field;
      */
      $this->timeout = $timeout;
      $this->session = $session;

      @session_start($this->session);

      if(!isset($_SESSION['logedstatus']))
      {
         $_SESSION['logedstatus'] = false;
      }

      if($_SESSION['logedstatus'] !== false)
      {
         if($this->timeout > 0)
         {
            if(isset($_SESSION['timestamp']) && (time() - $this->timeout) > $_SESSION['timestamp'])
            {
               $this->auth_destroy();
            } else
            {
               $_SESSION['timestamp'] = time();
            }
         }
         $this->logedstatus = $_SESSION['logedstatus'];
         $this->permission = $_SESSION['permission'];
         if(isset($_SESSION['user']))
         {
            $this->user = $_SESSION['user'];
         }
      } else
      {
         $this->logedstatus = false;
         $this->permission = false;
      }

      if($DB != false)
      {
         $this->DB = $DB;
         if($DB->serial < 20070328)
         {
            $this->error = 1;
         } else
         {
            if(!empty($table_params))
            {
               $this->parse_table_params($table_params);
            } else
            {
               $this->error = 2;
            }
         }
      }
   }


   /**
     * Parse teble from which autorize
     *
     * @param array $table_params
     */
   function parse_table_params($table_params)
   {
      foreach ($table_params as $key=>$value)
      {
         $this->clearance_string($key);
         $this->clearance_string($value);

         switch($key)
         {
            case 'table':
               $this->authsource['table'] = $value;
            break;

            case 'login':
               if($this->loginIsEmail === false) $this->authsource['login'] = $value;
            break;

            case 'pwd':
               $this->authsource['pwd'] = $value;
            break;

            case 'permissions':
               $this->authsource['permissions'] = $value;
            break;

            case 'lastloged':
               $this->authsource['lastloged'] = $value;
            break;

            case 'email':
               $this->authsource['email'] = $value;
               if($this->loginIsEmail === true) $this->authsource['login'] = $value;
            break;

            case 'name':
               $this->authsource['name'] = $value;
            break;

            case 'family':
               $this->authsource['family'] = $value;
            break;

            case 'valid':
               $this->authsource['valid'] = $value;
            break;

            default:
               $this->authsource[$key] = $value;
         }
      }
   }


   /**
     * Authorization function
     *
     * @param string $login
     * @param string $password
     */
   function authorization($login, $password)
   {
      $this->auth_destroy();
      session_start($this->session);

      if($this->loginIsEmail == false)
      {
         $this->clearance_string($login);
      } else
      {
         $login = $this->clearance_email($login);
      }
      $this->clearance_string($password);

      if(!empty($login) && !empty($password) && $login !== false && $password !== false)
      {
         if($this->root !== false && $this->rootpwd !== false)
         {
            if($this->root === $login && $this->rootpwd === $password)
            {
               $this->logedstatus = $_SESSION['logedstatus'] = true;
               $this->permission = $_SESSION['permission'] = 'system';
            }
         }

         if($this->DB !== false && $this->logedstatus === false && $this->authsource['table'] !== false && $this->authsource['login'] !== false && $this->authsource['pwd'] !== false)
         {
            if($this->crypt === true)
            {
               $sql = "SELECT * FROM %s WHERE %s = '%s' AND %s = MD5('%s')";
            } else
            {
               $sql = "SELECT * FROM %s WHERE %s = '%s' AND %s = '%s'";
            }

            if($this->authsource['valid'] != false)
            {
               $sql .= " AND " . $this->authsource['valid'] . " = '1'";
            }

            $this->DB->DB_QueryBuilder($sql, array($this->authsource['table'], $this->authsource['login'], $login, $this->authsource['pwd'], $password));
            $this->DB->Db_Query();

            if($this->DB->DB_GetRows() == 1)
            {
               $this->logedstatus = $_SESSION['logedstatus'] = true;

               $user_vars['id']    = $this->DB->DB_GetResult(0, 'id');
               $user_vars['login'] = $this->DB->DB_GetResult(0, $this->authsource['login']);
               $user_vars['name']  = $this->DB->DB_GetResult(0, 'name');
               $user_vars['email'] = $this->DB->DB_GetResult(0, $this->authsource['email']);

               $this->user = $_SESSION['user'] = $user_vars;

               if($this->authsource['permissions'] !== false)
               {
                  $permisson = $this->DB->DB_GetResult(0, $this->authsource['permissions']);

                  if($permisson == 'system')
                  {
                     $this->permission = $_SESSION['permission'] = $permisson;
                  } else
                  {
                     $this->permission = $_SESSION['permission'] = unserialize($permisson);
                  }
               }

               if($this->authsource['lastloged'] !== false)
               {
                  $this->DB->DB_QueryBuilder("UPDATE %s SET %s = NOW() WHERE %s = '%s'", array($this->authsource['table'], $this->authsource['lastloged'], $this->authsource['login'], $login));
                  $this->DB->DB_Query();
               }

               $this->redirect();
            } else
            {
               $this->error = 100;
               //$this->redirect();
            }
         } else
         {
            $this->error = 3;
         }
      } else
      {
         $this->error = 101;
         //$this->redirect();
      }
   }


   /**
     * Destroy authorization session
     *
     */
   function logout()
   {
      $this->auth_destroy();
      $this->redirect();
   }


   /**
     * Check string
     *
     * @param string $str
     */
   function clearance_string(&$str)
   {
      if(empty($str) || !preg_match('/^[a-z0-9_+=-]*$/i', $str))
      {
         $str = false;
         $this->error = 102;
      }
      return $str;
   }

   /**
     * Check e-mail
     *
     * @param string $email
     * @return string
     */
   function clearance_email($email)
   {
      if(eregi("^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*$",$email))
      {
         return $email;
      }

      $this->error = 103;
      return false;
   }

   /**
     * Reload page
     *
     */
   function redirect($destination = '')
   {
      if($destination == '') $destination = "http://".$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'];

      header("Location: ".$destination);

      exit();
   }

   /**
     * Reload parent window in framed page
     *
     * @return unknown
     */
   function frame_redirector()
   {
      $html  = "<html>\n";
      $html .= "<body>\n";
      $html .= "<script type=\"text/JavaScript\">\n";
      $html .= "top.location.href = \"http://".$_SERVER['HTTP_HOST'].rtrim(dirname($_SERVER['PHP_SELF']), '/\\')."\"\n";
      $html .= "</script>\n";
      $html .= "</body>\n";
      $html .= "</html>";

      return $html;
      exit();
   }

   /**
     * Destroy authorization sesson
     *
     */
   function auth_destroy()
   {
      $this->logedstatus = false;
      $this->permission = false;
      session_unregister('logedstatus');
      session_unregister('permission');
      session_unregister('timestamp');
      session_unregister('login');
      session_destroy();
   }
}

class Users extends auth
{
   var $user_table = array(
   'table'=>'meccano_users',
   'login'=>'login',
   'pwd'=>'pwd',
   'permissions'=>'rights',
   'lastloged'=>'lastlogin',
   'email'=>'email',
   'name'=>'name',
   'family'=>'family',
   'valid'=>'valid'
   );

   function Users($session = 'auth', $timeout = 0, &$DB, $user_table = '')
   {
      $this->crypt = true;

      if($user_table === '')
      {
         $user_table = &$this->user_table;
      }

      $this->auth($session, $timeout, $DB, $user_table);
   }

   function GetUserInfo($id)
   {
      isDigit($id);
      if($id == false) return false;

      $this->DB->sql = "SELECT * FROM " . $this->authsource['table'] . " WHERE id = '" . $id . "'";

      if($this->DB->DB_Fetch())
      {
         foreach ($this->DB->fetched[0] as $key => $value)
         {
            if($key == $this->authsource['permissions'] && $value != 'system')
            {
               $user_info[$key] = unserialize($value);
            } else
            {
               $user_info[$key] = $value;
            }
         }
         return $user_info;
      }

      return false;
   }

   function UpdateUserInfo($id, $vars)
   {
      isDigit($id);
      if($id == false) return false;
      if(!is_array($vars)) return false;
      $updates = array();

      $sql = "UPDATE ".$this->authsource['table']." SET ";
      if(!empty($vars['pwd']))
      {
         if($this->crypt == true)
         {
            $sql .= $this->authsource['pwd'] ." = MD5('%s'), ";
         } else
         {
            $sql .= $this->authsource['pwd'] ."='%s', ";
         }
         $updates[] = $vars['pwd'];
      }
      $sql .= $this->authsource['email'] ." = '%s', ";
      $updates[] = $vars['email'];
      $sql .= " name = '%s', family = '%s'";
      $updates[] = $vars['name'];
      $updates[] = $vars['family'];
      $sql .= " WHERE id = '" . $id . "'";

      $this->DB->DB_QueryBuilder($sql, $updates);

      return $this->DB->DB_Query();
   }
   
   function AddUser($vars)
   {
      if(!is_array($vars)) return false;
      
      $sql  = 'INSERT INTO '.$this->authsource['table'].' (';
      $sql .= $this->authsource['login'].', '.$this->authsource['pwd'].', ';
      $sql .= $this->authsource['email'].', '.$this->authsource['name'].', ';
      $sql .= $this->authsource['family'].', '.$this->authsource['valid'].') VALUES ("%s", ';
      if($this->crypt == true)
      {
         $sql .= 'MD5("%s")';
      } else
      {
         $sql .= '"%s"';
      }
      $sql .= ', "%s", "%s", "%s", "1")';
      $this->DB->DB_QueryBuilder($sql, array($vars['login'],$vars['pwd'],$vars['email'],$vars['name'],$vars['family']));

      return $this->DB->DB_Query();
   }
   
   function SetValid($id, $switch)
   {
      isDigit($id);
      isBool($switch);
      if($id == false) return false;

      if($switch == true)
      {
         $this->DB->sql = 'UPDATE '.$this->authsource['table'].' SET '.$this->authsource['valid'].' = "1" WHERE id = ' . $id;
      } else
      {
         $this->DB->sql = 'UPDATE '.$this->authsource['table'].' SET '.$this->authsource['valid'].' = "0" WHERE id = ' . $id;
      }

      return $this->DB->DB_Query();
   }
   
   function DeleteUsers($id)
   {

      $del = array();
      if(is_array($id))
      {
         $del = array_filter($id, 'isDigit');
      } else
      {
         if(isDigit($id) != false) $del[] = $id;
      }
      unset($id);

      if(count($del) > 0)
      {
         $del = implode(',', $del);
         $sql = 'DELETE FROM '.$this->authsource['table'].' WHERE id IN ('.$del.')';
         $this->DB->sql = $sql;
         return $this->DB->DB_Query();
      }

      return false;
   }
}
/*
DEVELOPMENT HISTORY:
0.4.4/20070328     + make compatiable with last (2.1.4) version of DB_SQL class
0.4.5/20070620     + make permission system for low access users
0.4.6/20070622     + add valid parameter for login entry
0.4.7/20070708     + improve working with email like logins
0.4.8/20070721     + improve error handling
0.4.9/20070724     - remove from session previous error stat
0.4.10/20071215    + add SetValid, DeleteUsers and AddUser methods


ERROR CODES:
1   - You should update DB library at least to version 2.1.4
2   - There is no params for authorization through DataBase
3   - System don't have pronounced DB object
100 - Fail authorization
101 - Empty or wrong input of authorization fields
102 - Invalid inputed string as login
103 - Inputed login isn't e-mail
*/
?>